package top.rainbowecho.article.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import top.rainbowecho.common.exception.BlogException;

import java.io.IOException;
import java.util.List;

/**
 * @author rainbow
 * @since 2020/10/10 17:07
 */
@Component
public class RedisProxy {
    private StringRedisTemplate redisTemplate;

    private ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Autowired
    public void setRedisTemplate(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 从redis中按照value类型查询值，如果redis中没有，就从数据库查询后放到redis中
     *
     * @param key 缓存键
     * @param dbCallback 数据库查询操作
     * @param <T> 列表元素的泛型类
     * @return 多个元素
     */
    public <T> List<T> getFromCache(String key, DBCallback<T> dbCallback) {
        try {
            List<T> data;
            Boolean hasKey = this.redisTemplate.hasKey(key);
            if (Boolean.TRUE.equals(hasKey)) {
                String json = this.redisTemplate.opsForValue().get(key);
                data = this.objectMapper.readValue(json, new TypeReference<List<T>>() {});
            } else {
                data = dbCallback.queryFromDb();
                this.redisTemplate.opsForValue().set(key, this.objectMapper.writeValueAsString(data));
            }
            return data;
        } catch (IOException e) {
            throw new BlogException(e.getMessage());
        }
    }

    /**
     * 从redis中删除某个键
     *
     * @param key redis键
     */
    public void evict(String key) {
        this.redisTemplate.delete(key);
    }
}
